package nautilus.lab.renderer;

import nautilus.lab.model.Coordinator3D;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Canvas;
import android.graphics.Color;
import android.support.v4.content.LocalBroadcastManager;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;

public class WaveView extends SurfaceView implements  Callback 
{
	private DrawingThread drawingThread;
	private Coordinator3D coord;
	private float touchedX, touchedY;
	private DataUpdateReceiver dataReceiver;
	
	private LocalBroadcastManager localBroadcastManager;

	public WaveView(Context context) {
		super(context);
		//setWillNotDraw(false);
		getHolder().addCallback(this);
		setFocusable(true);
		coord = new Coordinator3D(100, 100, 20, 20, 20);
		drawingThread = new DrawingThread(getHolder());
		localBroadcastManager = LocalBroadcastManager.getInstance(getContext());
		dataReceiver = new DataUpdateReceiver();
	}
	
	public WaveView(Context ctx, AttributeSet atts){
		super(ctx, atts);
		//setWillNotDraw(false);
		getHolder().addCallback(this);
		setFocusable(true);
		coord = new Coordinator3D(100, 100, 20, 20, 20);
		drawingThread = new DrawingThread(getHolder());
		localBroadcastManager = LocalBroadcastManager.getInstance(getContext());
		dataReceiver = new DataUpdateReceiver();
	}
	
	public WaveView(Context ctx, AttributeSet atts, int style){
		super(ctx, atts, style);
		//setWillNotDraw(false);
		getHolder().addCallback(this);
		setFocusable(true);
		coord = new Coordinator3D(100, 100, 20, 20, 20);
		drawingThread = new DrawingThread(getHolder());
		localBroadcastManager = LocalBroadcastManager.getInstance(getContext());
		dataReceiver = new DataUpdateReceiver();
	}

	@Override
	public void surfaceChanged(SurfaceHolder arg0, int format, int width, int height) {
		
	}

	@Override
	public void surfaceCreated(SurfaceHolder arg0) {
	}

	/* This is called immediately before a surface is being destroyed. */
	@Override
	public void surfaceDestroyed(SurfaceHolder holder) {
		drawingThread.terminate();
		localBroadcastManager.unregisterReceiver(dataReceiver);
	}
	
	public void surfaceRestart(){
		if(drawingThread != null)
			drawingThread.restart();
		
		if (dataReceiver == null) 
			dataReceiver = new DataUpdateReceiver();
		
		IntentFilter intentFilter = new IntentFilter("NAUTILUS_DATA_COMMUNICATION");
		localBroadcastManager.registerReceiver(dataReceiver, intentFilter);
	}
	
	@Override
	protected void onDraw(Canvas c){
		//super.onDraw(c);
		//Log.i("WaveView", "Drawing from WaveView");
		coord.draw(c);
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent me){
		touchedX = me.getX();
		touchedY = me.getY();
		int action = me.getAction();
		
		switch(action){
			case MotionEvent.ACTION_MOVE:
				coord.rotate(0.5f, 0.6f, 0.7f, -1);
			break;
		}
		
		return true;
	}
	
	/*	
	 * 
	 * 	Last update: Feb 19, 2013
	 * 
	 * 	I do all drawing action in another thread to prevent hanging from the 
	 * 	whole app
	 */
	class DrawingThread implements Runnable {
		private SurfaceHolder surfaceHolder;
		private boolean isRunning = false;
		volatile Thread thread;
		
		public DrawingThread(SurfaceHolder sh) {
			this.surfaceHolder = sh;
			isRunning = true;
			thread = new Thread(this);
			thread.start();
		}
		
		public void setRunning(boolean isR){
			this.isRunning = isR;
		}
		
		public void restart(){
			if(thread.getState() == Thread.State.TERMINATED){
				thread = new Thread(this);
				isRunning = true;
				thread.start();
				return;
			}
			
			//notify the existing thread
			synchronized(this){
				this.notify();
			}
		}
		
		public void terminate(){
			isRunning = false;
			try {
				thread.join();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			//thread.interrupt();
		}
		
		@Override
		public void run(){
			Canvas c = null;
			while(this.isRunning){				
				try{
					if(surfaceHolder.getSurface().isValid())
					{
						c = this.surfaceHolder.lockCanvas();
						synchronized(this.surfaceHolder)	{
							c.drawColor(Color.BLACK);//fill the whole background
							WaveView.this.onDraw(c);
						}
					}
				}
				finally{
					if(c != null)
						this.surfaceHolder.unlockCanvasAndPost(c);
				}	
			}
		}
	}
	
	class DataUpdateReceiver extends BroadcastReceiver {
	    @Override
	    public void onReceive(Context context, Intent intent) {
	        if (intent.getAction().equals("SOCKET_RECEIVED")) {
	        	//Do stuff - maybe update my view based on the changed DB contents
	        	WaveView.this.coord.rotate(0.5f, 0.6f, 0.7f, -1);
	        }
	    }
	}
}
